package gameStates.gui;

import networking.messages.syncMessages.ValueType;
import gameStates.absGamesStates.gui.AbsSpawnState;
import gameStates.passes.AbsPassManagerState;
import interfaces.spawnMenu.AbsSpawnMenu;
import interfaces.spawnMenu.SpawnMenu;
import interfaces.spawnMenu.costumize.CustomizeWindow;
import logic.common.game.Game;
import logic.common.player.Player;
import logic.common.player.playerListeners.HunterChangedEvent;
import logic.common.player.playerListeners.KillAssistEvent;
import logic.common.player.playerListeners.KillEvent;
import logic.common.player.playerListeners.MissionAssistEvent;
import logic.common.player.playerListeners.NearStationChangedEvent;
import logic.common.player.playerListeners.PlayerListener;
import logic.common.player.playerListeners.PlayerStationListener;
import logic.common.player.playerListeners.PlayerValueListener;
import logic.common.player.playerListeners.RespawnEvent;
import logic.common.player.playerListeners.SelectedSpawnChangedEvent;
import logic.common.player.playerListeners.TargetChangedEvent;
import logic.ships.hunter.Hunter;
import logic.status.StatusChangedEvent;
import main.InitGame;
import main.listeners.listenerClasses.GameListener;
import map.spawnStation.SpawnPosition;
import map.spawnStation.SpawnStation;
import map.spawnStation.stationListeners.ConquerHelpedEvent;
import map.spawnStation.stationListeners.SpawnStationListener;
import map.spawnStation.stationListeners.StationConqueredEvent;

/**
 * Implements a SpawnMenuState that displays a {@link SpawnMenu}.
 * 
 * @author Wasserleiche
 */
public class SpawnMenuState extends AbsSpawnState {
	
	private Game game;
	private SpawnStation nearSpawnStation;
	private SpawnStationListener stationListener;
	
	/**
	 * Constructs a new SpawnMenuState and creates a new {@link SpawnMenu}.
	 */
	public SpawnMenuState(Game game, AbsPassManagerState passManagerState) {
		super(passManagerState, true);
		this.game = game;
		
		addListenerToClearer(new GameListener() {
			@Override
			public void gameStarted() {
				setActive(true);
			}
			
			@Override
			public void gameFinished() {
				setActive(false);
			}
			
			@Override
			public void gameDestroyed() {
				setActive(false);
			}
		});
		
		initInterface(game);
		
		final Player currentPlayer = game.getCurrentPlayer();
		currentPlayer.addPlayerListener(new PlayerListener() {
			@Override
			public void respawned(RespawnEvent event) {
				if(isActive()) InitGame.get().toggleSpawnMenu();
			}
			
			@Override
			public void hunterChanged(HunterChangedEvent event) {}
			@Override
			public void targetChanged(TargetChangedEvent event) {}
			@Override
			public void killed(KillEvent event) {}
			@Override
			public void killAssist(KillAssistEvent event) {}
			@Override
			public void missionAssist(MissionAssistEvent event) {}
		});
		
		addListener(currentPlayer, new PlayerValueListener() {
			@Override
			public void valueChanged(StatusChangedEvent event) {
				if(event.getType() == ValueType.Money) updateMoney(event.getIntValue());
			}
		});
		
		stationListener = new SpawnStationListener() {
			@Override
			public void stationNeutralized() {
				if(currentPlayer.isAlive()) getSpawnMenu().enableCustomizeWindow(false);
			}
			
			@Override
			public void conquered(StationConqueredEvent event) {
				if(nearSpawnStation.getTeam() == currentPlayer.getTeam()) 
					getSpawnMenu().enableCustomizeWindow(true);
			}
			
			@Override
			public void helpedConquer(ConquerHelpedEvent event) {}
		};
		
		addListener(currentPlayer, new PlayerStationListener() {
			@Override
			public void nearSpawnStationChanged(NearStationChangedEvent event) {
				SpawnPosition spawn = event.getSpawnPos();
				boolean enable = spawn != null && spawn.getTeam() == currentPlayer.getTeam();
				getSpawnMenu().enableCustomizeWindow(enable);
				
				if(nearSpawnStation != spawn && nearSpawnStation != null) nearSpawnStation.removeSpawnStationListener(stationListener);
				if(spawn instanceof SpawnStation) {
					nearSpawnStation = (SpawnStation)spawn;
					nearSpawnStation.addSpawnStationListener(stationListener);
				}
			}
			
			@Override
			public void selectedSpawnPositionChanged(SelectedSpawnChangedEvent event) {}
		});
	}
	
	/**
	 * Creates a new {@link SpawnMenu} and attaches it to the display.
	 */
	public void initInterface(Game game) {
		interfaceElement = new SpawnMenu(this, game);
	}
	
	/**
	 * Returns the {@link SpawnMenu}.
	 * @return The {@link SpawnMenu}.
	 */
	@Override
	public AbsSpawnMenu getSpawnMenu() { return (AbsSpawnMenu)interfaceElement; }
	
	/**
	 * Restores this SpawnMenuState. Also creates a new {@link SpawnMenu}.
	 */
	@Override
	public void restore() {
		super.restore();
		initInterface(game);
		CustomizeWindow window = getSpawnMenu().getCustomWindow();
		guiDisp.addWidget(window);
		window.changeHunter(game.getCurrentPlayer().getHunter());
		AbsSpawnMenu spawnMenu = getSpawnMenu();
		spawnMenu.restore();
	}
	
	@Override
	public boolean isReady() {
		return getSpawnMenu().isReady();
	}
	
	@Override
	public Hunter getSelectedHunter() {
		return getSpawnMenu().getSelectedHunter();
	}
	
	@Override
	public SpawnPosition getSelectedSpawnLocation() {
		return getSpawnMenu().getSelectedSpawnLocation();
	}
	
	@Override
	public void showMiniMap() {
		AbsSpawnMenu spawnMenu = getSpawnMenu();
		spawnMenu.setCurrentWindow(spawnMenu.getSpawnMap());
	}
	
	@Override
	public boolean isShowingMiniMap() {
		AbsSpawnMenu spawnMenu = getSpawnMenu();
		return spawnMenu.getCurrentWindow() == spawnMenu.getSpawnMap();
	}
}